/* eslint-disable */
const hljs = require('highlight.js');
const MarkdownIt = require('markdown-it');
const MarkdownItContainer = require('markdown-it-container');
const { compileTemplate, TemplateCompiler } = require('@vue/compiler-sfc');
const md = MarkdownIt().use(MarkdownItContainer,'demo-api',{
  validate: function(params) {
    return params.trim().match(/^demo-api\s*(.*)$/);
  },
  render: function (tokens, idx) {
    var m = tokens[idx].info.trim().match(/^demo-api\s*(.*)$/);
    if (tokens[idx].nesting === 1) {
      // opening tag
      return `<h2>${md.utils.unescapeAll(m[1])}</h2><demo-api>\n`;
    } else {
      // closing tag
      return '</demo-api>\n';
    }
  }
});
md.use(MarkdownItContainer,'alert',{
  validate: function(params) {
    return params.trim().match(/^alert\s*(.*)$/);
  },
  render: function (tokens, idx) {
    var m = tokens[idx].info.trim().match(/^alert\s*(.*)$/);
    if (tokens[idx].nesting === 1) {
      let alertType = m[1].trim() || 'primary';
      // opening tag
      return `<div class="alert alert-${md.utils.unescapeAll(alertType)}">\n`;
    } else {
      // closing tag
      return '</div>\n';
    }
  }
});
function getScript(content) {
  const result = content.match(/<(script)>([\s\S]+)<\/\1>/);
  return result && result[2] ? result[2].trim() : '';
}
function getTemplate(content) {
  content = content.trim();
  if (!content) {
    return content;
  }
  return content.replace(/<(script|style)[\s\S]+<\/\1>/g, '').trim();
}
function getUUID(prefix){
  return String(Math.random() + Math.random()).replace(/\d\.\d{4}/, prefix || "vue-bootstrap-plus");
}
function pad(source) {
  return source
    .split(/\r?\n/)
    .map(line => `  ${line}`)
    .join('\n')
}
const templateReplaceRegex = /<template>([\s\S]+)<\/template>/g;
function getDemoComponenCode(code){
  code = md.utils.unescapeAll(code);
  let script = getScript(code);
  let template = getTemplate(code);
  if (templateReplaceRegex.test(template)) {
    template = template.replace(templateReplaceRegex, '$1')
  }
  const finalOptions = {
    id: getUUID(),
    source: template,
    filename: 'inline-component',
    compiler: TemplateCompiler,
    compilerOptions: {
      mode: 'function',
    }
  }
  const compiled = compileTemplate(finalOptions)
  // tips
  if (compiled.tips && compiled.tips.length) {
    compiled.tips.forEach(tip => {
      console.warn(tip)
    })
  }
  // errors
  if (compiled.errors && compiled.errors.length) {
    console.error(
      `\n  Error compiling template:\n${pad(compiled.source)}\n` +
        compiled.errors.map(e => `  - ${e}`).join('\n') +
        '\n',
    )
  }
  let demoComponentCode = `
    ${(compiled.code).replace('return function render','function render')}
  `
  // todo: 这里采用了硬编码有待改进
  script = script.trim()
  if (script) {
    script = script
      .replace(/export\s+default/, 'const democomponentExport =')
      .replace(/import ({.*}) from 'vue'/g, (s, s1) => `const ${s1} = Vue`)
      .replace(/import ({.*}) from 'vue-bootstrap-plus'/g, (s, s1) => `const ${s1} = require('vue-bootstrap-plus')`)
  } else {
    script = 'const democomponentExport = {}'
  }
  demoComponentCode = `(function() {
    ${demoComponentCode}
    ${script}
    return {
      render,
      ...democomponentExport
    }
  })()`;
  return demoComponentCode;
}
module.exports = (source) => {
	let content = md.render(source);
  let codeReg = /<pre><code [^>]*language-html[^>]*>(((?!<\/code><\/pre>)[\s\S])*)<\/code><\/pre>/g;
  const demoCodes = [];
  let execResult = codeReg.exec(content);
  let start = 0;
  /**
   * xxxxxxx
   * ```html
   * ...
   * ...
   * ```
   * xxxx
   * xxxx
   */
  const docCode = [];
  const allDemoComponentCode = [];
  let demoComponentId = 0;
  while(execResult){
    // console.log(execResult[1]);
    // console.log(start,execResult.index);
    docCode.push(content.substring(start,execResult.index).trim());
    //一个demo的完整代码
    const demoComponentCode = getDemoComponenCode(execResult[1]);
    const compName = `DemoComponent${demoComponentId}`;
    allDemoComponentCode.push(`${compName}: ${demoComponentCode}`);
    const hljsCode = hljs.highlight(md.utils.unescapeAll(execResult[1]),{
      language: 'html',
      ignoreIllegals: true
    }).value;
    docCode.push(`<demo>
      <${compName} />
      <template #demoCode><pre v-pre><code>${hljsCode}</code></pre></template>
    </demo>`);
    // console.log(execResult[0].length,execResult[1].length,execResult.index);
    demoCodes.push(execResult[1]);
    start = (execResult[0].length + execResult.index);
    execResult = codeReg.exec(content);
    demoComponentId++;
  }
  if(start < content.length - 1){
    /**
     * ....
     * <demo-api>
     * .....
     * </demo-api>
     * ...
     * ....
     * <demo-api>
     * .....
     * </demo-api>
     */
    content = content.substring(start);
    codeReg = /<demo-api>(((?!<\/demo-api>)[\s\S])*)<\/demo-api>/g;
    execResult = codeReg.exec(content);
    start = 0;
    while(execResult){
      docCode.push(content.substring(start,execResult.index).trim());
      let tableHtml = execResult[1].trim().replace(/(^<p>)|(<\/p>$)/g,'');
      tableHtml = md.utils.unescapeAll(tableHtml);
      tableHtml = tableHtml.replace("<table>","<table class='table table-responsive table-hover'>");
      docCode.push(`<div class='demo-api'>
        ${tableHtml}
      </div>`);
      start = (execResult[0].length + execResult.index);
      execResult = codeReg.exec(content);
    }
    docCode.push(content.substring(start));
  }
  const result = `<template>
    ${docCode.join("")}
  </template>
  <script>
    import * as Vue from 'vue';
    export default {
      components: {
        ${allDemoComponentCode.join(",")}
      }
    }
  </script>`;
  return result;
};